package org.weasel.data;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jdom.Element;
import org.weasel.business.Developer;
import org.weasel.business.Project;
import org.weasel.business.Utilities;


public class SettingsManager {
	private static XMLManager xmlMan;
	private boolean fileExists = true;
	
	public SettingsManager(String path) throws Exception {
		boolean existsSettingsFile = Utilities.existsFile(path);
		xmlMan = new XMLManager(path);
		if(!existsSettingsFile) {
			createDocumentStructure();
			fileExists = false;
		}
	}
	
	public boolean getFileExists() {
		return this.fileExists;
	}


	private void createDocumentStructure() throws IOException {
		xmlMan.createRootElement("settings");
		Element root = xmlMan.getRootElement();
		
		Element companyName = new Element("companyName");
		xmlMan.addElement(root, companyName);
		
		Element userStory = new Element("userStory");
		xmlMan.addElement(root, userStory);
		
		Element developers = new Element("developers");
		xmlMan.addElement(root, developers);
		
		Element projects = new Element("projects");
		xmlMan.addElement(root, projects);
		
		save();
	}
	
	/***
	 * This method updates the text of the company in the settings.xml
	 * @param newCompanyName
	 * @throws Exception
	 */
	public void setCompanyName(String newCompanyName) throws Exception {
		Element companyNameElement = xmlMan.getElementByQuery("/descendant::companyName");
		companyNameElement.setText(newCompanyName);
		save();
	}
	
	//needed to store which userstory should be opened in the view
	//since no variable passing now...IMPORTANT TO CHANGE
	//TODO change this
	public void setuserStory(String newuserStoryID) throws Exception {
		Element companyNameElement = xmlMan.getElementByQuery("/descendant::userStory");
		companyNameElement.setText(newuserStoryID);
		save();
	}
	
	public String getuserStory() throws Exception {
		Element userStoryElement = xmlMan.getElementByQuery("/descendant::userStory");
		return userStoryElement.getText();
	}
	
	
	/***
	 * This method returns the name of the company which is stored in the actual
	 * settings.xml
	 * @return
	 * @throws Exception
	 */
	public String getCompanyName() throws Exception {
		Element userStoryElement = xmlMan.getElementByQuery("/descendant::companyName");
		return userStoryElement.getText();
	}
	
	/***
	 * This method returns an arraylist of projects which are stored in the settings.xml
	 * @return
	 * @throws Exception
	 */
	public ArrayList<Project> getProjects() throws Exception {
		ArrayList<Project> projects = new ArrayList<Project>();
		Project project;
		String id, name, path;
		Element projectsElement = getProjectsElement();
		List projectsList = projectsElement.getChildren();
		for (int i = 0; i < projectsList.size(); i++) {
			id = ((Element)projectsList.get(i)).getChild("id").getText();
			name = ((Element)projectsList.get(i)).getChild("name").getText();
			path = ((Element)projectsList.get(i)).getChild("path").getText();
			project = new Project(id, name, path, getDevelopers());
			projects.add(project);
		}
		return projects;
	}

	/***
	 * This method returns an xml element which holds all the project elements in
	 * the settings.xml
	 * @return
	 * @throws Exception
	 */
	private Element getProjectsElement() throws Exception {
		Element projectsElement = xmlMan.getElementByQuery("/descendant::projects");
		return projectsElement;
	}
	
	/***
	 * This method creates a new project, stores it in the settings.xml, adds it to the arraylist
	 * of projects of the settings object and returns it
	 * @param project TODO
	 * @return
	 * @throws Exception
	 */
	public void storeProject(Project project) throws Exception {		
		Element projectsElement = getProjectsElement();
		Element newProject = new Element("project");
		xmlMan.addElement(projectsElement, newProject);
		
		Element idElement = new Element("id");
		idElement.setText(project.getId());
		xmlMan.addElement(newProject, idElement);
		
		Element projectName = new Element("name");
		projectName.setText(project.getName());
		xmlMan.addElement(newProject, projectName);
		
		Element projectPath	= new Element("path");
		projectPath.setText(project.getPath());
		xmlMan.addElement(newProject, projectPath);
		save();
	}
	
	/***
	 * This method deletes a project passed as parameter from the settings.xml,
	 * deletes the xml file of the project and deletes the project from the
	 * arraylist of projects
	 * @param project
	 * @throws Exception
	 */
	public void deleteProject(Project project) throws Exception {
		if(Utilities.existsFile(project.getPath())) {
			//deletes the project xml file
			Utilities.deleteFile(project.getPath());
		}
		
		//deletes the project from the arraylist
		//settings.getProjects().remove(project);
		
		//removes the project entry in the settings.xml if it exists 
		Element projectsElement = getProjectsElement();
		Element projectElement = xmlMan.getElementByQuery("/descendant::project[id=\"" + project.getId() + "\"]");
		if(!projectElement.equals(null)) {
			projectsElement.removeContent(projectElement);
			save();
		}
	}
	
	public void storeDeveloper(Developer d) throws Exception {
		Element developerEl = new Element("developer");
		Element idEl = new Element("id");
		idEl.setText(d.getId());
		Element nameEl = new Element("name");
		nameEl.setText(d.getName());
		Element mailEl = new Element("email");
		mailEl.setText(d.getEMail());
		Element positionEl = new Element("position");
		positionEl.setText(d.getPosition());
		
		developerEl.addContent(idEl);
		developerEl.addContent(nameEl);
		developerEl.addContent(mailEl);
		developerEl.addContent(positionEl);
		
		//retrieve the parent element "developers" where to attach the developer node
		Element developersEl = getDevelopersElement();
		xmlMan.addElement(developersEl, developerEl);
		
		save();
	}
	
	public void deleteDeveloper(Developer developer) throws Exception {
		//settings.getDevelopers().remove(developer);
		
		//removes the developer entry in the settings.xml if it exists 
		Element developersEl = getDevelopersElement();
		Element developerEl = xmlMan.getElementByQuery("/descendant::developer[id=\"" + developer.getId() + "\"]");
		if(!developerEl.equals(null)) {
			developersEl.removeContent(developerEl);
			save();
		}
	}

	/***
	 * This method reads out all the developers from the settings.xml and
	 * stores them into the developers array list of the settings object
	 * @throws Exception
	 */
	public ArrayList<Developer> getDevelopers() throws Exception {
		ArrayList<Developer> developers = new ArrayList<Developer>();
		Developer developer;
		String id, name, mail, position;
		Element projectsElement = getDevelopersElement();
		List developersList = projectsElement.getChildren();
		for (int i = 0; i < developersList.size(); i++) {
			id = ((Element)developersList.get(i)).getChild("id").getText();
			name = ((Element)developersList.get(i)).getChild("name").getText();
			mail = ((Element)developersList.get(i)).getChild("email").getText();
			position = ((Element)developersList.get(i)).getChild("position").getText();
			developer = new Developer(id, name, mail, position);
			developers.add(developer);
		}
		return developers;
	}
	
	/***
	 * This method returns an xml element which holds all the developer
	 * elements
	 * @return
	 * @throws Exception
	 */
	private Element getDevelopersElement() throws Exception {
		return xmlMan.getElementByQuery("/descendant::developers");
	}

	/**
	 * Saves the XML file
	 * @throws IOException
	 */
	private static void save() throws IOException{
		xmlMan.writeToFile();
	}
}
